package com.ctshk.rpc.guide.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.*;
import com.ctshk.common.enums.bus.BusConst;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.mail.core.MailTemplate;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.guide.dto.GuideCollarExcelDTO;
import com.ctshk.rpc.guide.dto.GuideCollarListDTO;
import com.ctshk.rpc.guide.dto.GuideCollarQueryDTO;
import com.ctshk.rpc.guide.entity.GuideCollar;
import com.ctshk.rpc.guide.entity.GuideCollarCertificates;
import com.ctshk.rpc.guide.entity.GuideCollarScheduling;
import com.ctshk.rpc.guide.enums.GroupCollarCertificatesStatus;
import com.ctshk.rpc.guide.enums.GroupCollarCertificatesType;
import com.ctshk.rpc.guide.mapper.GuideCollarCertificatesMapper;
import com.ctshk.rpc.guide.mapper.GuideCollarMapper;
import com.ctshk.rpc.guide.mapper.GuideCollarSchedulingMapper;
import com.ctshk.rpc.guide.req.*;
import com.ctshk.rpc.guide.service.IGuideCollarService;
import com.ctshk.rpc.system.req.SysMessageReq;
import com.ctshk.rpc.system.service.IMainDataTableService;
import com.ctshk.rpc.system.service.ISysPermissionService;
import com.ctshk.rpc.system.service.ISystemMessageService;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 导领信息表 服务实现类
 * </p>
 *
 * @author 谢诗宏
 * @since 2021-02-25
 */
@DubboService
public class GuideCollarServiceImpl extends ServiceImpl<GuideCollarMapper, GuideCollar> implements IGuideCollarService {

    private final Long LDXXGL = 36405846791421952l;//领队信息管理
    private final Long DYXXGL = 36450675214778368l;//导游信息管理 1@1.1
    private final String emailReg = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";
    @Autowired
    private GuideCollarCertificatesMapper guideCollarCertificatesMapper;

    @DubboReference
    private IMainDataTableService mainDataTableService;

    @DubboReference
    private ISystemMessageService systemMessageService;

    @DubboReference
    private ISysPermissionService sysPermissionService;

    @Autowired
    private GuideCollarSchedulingMapper guideCollarSchedulingMapper;

    @Autowired
    private GuideCollarSchedulingServiceImpl guideCollarSchedulingService;

    @Autowired
    private MailTemplate mailTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(GuideCollarAddReq req, TokenUser tokenUser) {
        if (StringUtils.isNotEmpty(req.getEmployeeNumber())) {
            //导领员工号不能重复
            List<GuideCollar> gc = baseMapper.selectList(Wrappers.<GuideCollar>lambdaQuery()
                    .select(GuideCollar::getId)
                    .eq(GuideCollar::getEmployeeNumber, req.getEmployeeNumber())
                    .eq(GuideCollar::getIsDeleted, IsDeletedCode.NO.getCode())
            );
            if (gc != null && gc.size() > 0) {
                throw new BusinessException(SystemError.GUIDE_41005);
            }
        }
        if (req.getCertificatesList() != null) {
            List<Long> collect = req.getCertificatesList().stream().map(e -> e.getCertificatesTypeId()).collect(Collectors.toList());
            Set<Long> set = new HashSet<>(collect);
            //去重后的证件数量必须相等不相等就是有重复的证件ID
            if (set.size() != collect.size()) {
                throw new BusinessException(SystemError.GUIDE_410013);
            }
        }
        GuideCollar guideCollar = EntityUtil.copy(req, GuideCollar.class);
        long id = SnowflakeIdWorker.nextId();
        LocalDate now = LocalDate.now();
        LocalDateTime now1 = LocalDateTime.now();
        guideCollar.setId(id);
        guideCollar.setStatus(GuideCollarStatus.STATUS_1.getCode());
        guideCollar.setCreateId(tokenUser.getId());
        guideCollar.setModifiedId(tokenUser.getId());
        guideCollar.setGmtModified(now1);
        guideCollar.setIsDeleted(IsDeletedCode.NO.getCode());
        guideCollar.setGmtCreate(now1);
        guideCollar.setOurGroup(0);
        guideCollar.setCertificatesStatus(GroupCollarCertificatesStatus.CERTIFICATE_STATUS_1.getCode());
        //默认入行时间为0
        guideCollar.setIndustryGroup(0);
        //计算入行时间
        if (null != req.getIndustryTime()) {
            int year = Period.between(req.getIndustryTime(), now).getDays() / 365;
            guideCollar.setIndustryGroup(year);
        }
        Long CertificatesTypeId = null;
        //判断该加导游证还是导领证
        if (req.getType() == GuideCollarTypeTwo.GUIDE.getCode()) {
            CertificatesTypeId = GroupCollarCertificatesType.LDZ.getCode();//領隊證
        } else {
            CertificatesTypeId = GroupCollarCertificatesType.DYZ.getCode();//導遊證
        }
        //計算證件狀態
        for (GuideCollarCertificatesReq guideCollarCertificatesReq : req.getCertificatesList()) {
            //取主要的导游证或者导领证为失效时间
            if (guideCollarCertificatesReq.getCertificatesTypeId().equals(CertificatesTypeId)) {
                int years = Period.between(now, guideCollarCertificatesReq.getEffectiveTime()).getYears();
                int months = Period.between(now, guideCollarCertificatesReq.getEffectiveTime()).getMonths();
                int days = Period.between(now, guideCollarCertificatesReq.getEffectiveTime()).getDays();
                int i = years * 365 + months * 30 + days;
                if (i > 30) {
                    guideCollar.setCertificatesStatus(GuideCollarCertificatesStatus.STATUS_1.getCode());
                } else if (i < 0) {
                    guideCollar.setCertificatesStatus(GuideCollarCertificatesStatus.STATUS_3.getCode());
                } else {
                    guideCollar.setCertificatesStatus(GuideCollarCertificatesStatus.STATUS_2.getCode());
                }
            }
        }
        int insert = baseMapper.insert(guideCollar);
        if (insert > 0) {
            //新增成功后添加相关证件
            for (GuideCollarCertificatesReq certificates : req.getCertificatesList()) {
                GuideCollarCertificates guideCollarCertificates = EntityUtil.copy(certificates, GuideCollarCertificates.class);
                guideCollarCertificates.setGuideCollarId(id);
                guideCollarCertificatesMapper.insert(guideCollarCertificates);
            }
            List<GuideCollar> gcs = new ArrayList<>();
            gcs.add(guideCollar);
            //新增成功后就给他安排礼拜天休假
            List<GuideCollar> guideCollars = setWork(gcs);
            //没有安排成功就给他加对应的月假
            if (guideCollars.size() > 0) {
                baseMapper.updateById(guideCollars.get(0));
            }
        } else {
            return Result.failed(SystemError.GUIDE_41006);
        }
        return Result.success(id);
    }

    @Override
    public PageResponse<GuideCollarListDTO> list(GuideCollarListReq req) {
        Page<GuideCollar> page = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<GuideCollar> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(GuideCollar::getType, req.getType())
                .like(StringUtils.isNotBlank(req.getEmployeeNumber()), GuideCollar::getEmployeeNumber, req.getEmployeeNumber())
                .eq(GuideCollar::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(null != req.getLeaderTypeId(), GuideCollar::getLeaderTypeId, req.getLeaderTypeId())
                .eq(null != req.getLeaderLevelId(), GuideCollar::getLeaderLevelId, req.getLeaderLevelId())
                .eq(null != req.getGender(), GuideCollar::getGender, req.getGender())
                .eq(null != req.getStatus(), GuideCollar::getStatus, req.getStatus())
                .eq(null != req.getCertificatesStatus(), GuideCollar::getCertificatesStatus, req.getCertificatesStatus())
                .eq(null != req.getDepartmentId(), GuideCollar::getDepartmentId, req.getDepartmentId())
                .between(null != req.getEntryTimeBegin() && null != req.getEntryTimeEnd(), GuideCollar::getEntryTime, req.getEntryTimeBegin(), req.getEntryTimeEnd())
                .orderByDesc(GuideCollar::getEntryTime);
        Page<GuideCollar> iPage = baseMapper.selectPage(page, queryWrapper);
        List<GuideCollar> records = iPage.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return new PageResponse<>(new ArrayList<>(), iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        }
        List<GuideCollarListDTO> listDTOS = EntityUtil.copyList(records, GuideCollarListDTO.class);

        Long CertificatesTypeId = null;
        //判断该加导游证还是导领证
        if (req.getType() == GuideCollarTypeTwo.GUIDE.getCode()) {
            CertificatesTypeId = GroupCollarCertificatesType.LDZ.getCode();//領隊證
        } else {
            CertificatesTypeId = GroupCollarCertificatesType.DYZ.getCode();//導遊證
        }
        for (GuideCollarListDTO guideCollarListDTO : listDTOS) {
            QueryWrapper<GuideCollarCertificates> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(GuideCollarCertificates::getGuideCollarId, guideCollarListDTO.getId())
                    .eq(GuideCollarCertificates::getCertificatesTypeId, CertificatesTypeId);
            GuideCollarCertificates selectOne = guideCollarCertificatesMapper.selectOne(wrapper);
            if (null != selectOne) {
                guideCollarListDTO.setEffectiveTime(selectOne.getEffectiveTime());
            }
        }
        return new PageResponse<>(listDTOS, iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
    }

    @Override
    public GuideCollarQueryDTO query(GuideCollarQueryReq req) {
        GuideCollar guideCollar = baseMapper.selectById(req.getId());
        GuideCollarQueryDTO guideCollarQueryDTO = EntityUtil.copy(guideCollar, GuideCollarQueryDTO.class);
        if (null != guideCollar.getId()) {
            QueryWrapper<GuideCollarCertificates> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(GuideCollarCertificates::getGuideCollarId, guideCollar.getId());
            List<GuideCollarCertificates> certificatesList = guideCollarCertificatesMapper.selectList(wrapper);
            List<GuideCollarCertificatesReq> certificatesReqList = EntityUtil.copyList(certificatesList, GuideCollarCertificatesReq.class);
            if (CollectionUtils.isNotEmpty(certificatesReqList)) {
                guideCollarQueryDTO.setCertificatesList(certificatesReqList);
            }
        }
        return guideCollarQueryDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result update(GuideCollarUpdateReq req, TokenUser tokenUser) {
        LocalDateTime now = LocalDateTime.now();
        GuideCollar guideCollar = EntityUtil.copy(req, GuideCollar.class);
        guideCollar.setModifiedId(tokenUser.getId());
        guideCollar.setGmtModified(now);
        int i = baseMapper.updateById(guideCollar);
        if (i > 0) {
            //重新添加导领证件
            QueryWrapper<GuideCollarCertificates> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(GuideCollarCertificates::getGuideCollarId, req.getId());
            int delete = guideCollarCertificatesMapper.delete(queryWrapper);
            if (delete > 0) {
                List<GuideCollarCertificates> certificates = EntityUtil.copyList(req.getCertificatesList(), GuideCollarCertificates.class);
                for (GuideCollarCertificates guideCollarCertificates : certificates) {
                    guideCollarCertificatesMapper.insert(guideCollarCertificates);
                }
            }
        }
        return Result.success(req.getId());
    }

    @Override
    public Result updateTransferAgency() {
        QueryWrapper<GuideCollar> qwgc = new QueryWrapper<>();
        qwgc.lambda().eq(GuideCollar::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(GuideCollar::getTransferAgencyDate, LocalDate.now());
        List<GuideCollar> guideCollars = baseMapper.selectList(qwgc);
        guideCollars.stream().forEach(e -> {
            if (e.getTransferAgencyId() != null && e.getTransferAgencyId() != e.getDepartmentId()) {
                e.setDepartmentId(e.getTransferAgencyId());
                e.setDepartmentName(e.getTransferAgencyName());
                baseMapper.updateById(e);
            }
        });
        return Result.success(guideCollars.size());
    }

    @Override
    public Result topAndBottomTransferAgency() {
        QueryWrapper<GuideCollar> qwgc = new QueryWrapper<>();
        qwgc.lambda().eq(GuideCollar::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(GuideCollar::getBePromotedDare, LocalDate.now());//升职
        List<GuideCollar> guideCollars = baseMapper.selectList(qwgc);
        guideCollars.stream().forEach(e -> {
            if (e.getBePromotedLevelId() != null && e.getBePromotedLevelId() != e.getLeaderLevelId()) {
                e.setLeaderLevelId(e.getBePromotedLevelId());
                e.setLeaderLevelName(e.getBePromotedLevelName());
                baseMapper.updateById(e);
            }
        });
        qwgc.clear();//清空条件下面是离职的
        qwgc.lambda().eq(GuideCollar::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(GuideCollar::getQuitDate, LocalDate.now());
        List<GuideCollar> guideCollars1 = baseMapper.selectList(qwgc);
        guideCollars1.stream().forEach(e -> {
            if (e.getQuitDate() != null && LocalDate.now().isEqual(e.getQuitDate())) {
                e.setStatus(GuideCollarStatus.STATUS_2.getCode());//离职时间到期要改状态
                baseMapper.updateById(e);
            }
        });
        return Result.success(guideCollars.size() + guideCollars1.size());
    }

    @Override
    public Result examineContractExpired() {
        QueryWrapper<GuideCollar> qwgc = new QueryWrapper<>();
        //不是删除的数据，合约天数大于当前工作天数，不为离职和黑名单状态
        qwgc.eq("is_deleted", IsDeletedCode.NO.getCode())
                .apply("contract_period * 365 > to_days(now())-to_days(entry_time)")
                .notIn("status", GuideCollarStatus.STATUS_2.getCode(), GuideCollarStatus.STATUS_4.getCode());
        List<GuideCollar> guideCollars = baseMapper.selectList(qwgc);
        //遍历这些合约到期的用户 并修改位离职状态
        guideCollars.forEach(e -> e.setStatus(GuideCollarStatus.STATUS_2.getCode()));
        boolean b = updateBatchById(guideCollars);
        return Result.success(b);
    }

    @Override
    public Result vacationStatistics() {
        QueryWrapper<GuideCollar> qwgc = new QueryWrapper<>();
        qwgc.eq("is_deleted", IsDeletedCode.NO.getCode())
                .notIn("status", GuideCollarStatus.STATUS_2.getCode(), GuideCollarStatus.STATUS_4.getCode());
        List<GuideCollar> guideCollars = baseMapper.selectList(qwgc);
        //给这些人安排每个礼拜天休假，如果礼拜天有安排了，那么就给他记录到月假天数，
        List<GuideCollar> newGuideCollars = setWork(guideCollars);
        boolean b = updateBatchById(newGuideCollars);
        return Result.success(b);
    }

    /**
     * 给导领设置休息
     *
     * @return
     */
    private List<GuideCollar> setWork(List<GuideCollar> guideCollars) {
        LocalDate date = LocalDate.now();
        LocalDate dateFirst = LocalDate.now();
        //当前月的所有礼拜天
        List<LocalDate> weekDay = new ArrayList<>();
        while (Period.between(dateFirst, date).getMonths() < 1) {
            DayOfWeek week = date.getDayOfWeek();
            if (week == DayOfWeek.SUNDAY) {
                weekDay.add(date);
            }
            //每次比较完后向后推移一天
            date = date.plusDays(1);
        }
        List<GuideCollar> newGuideCollars = new ArrayList<>();
        //给这些人安排每个礼拜天休假，如果礼拜天有安排了，那么就给他记录到月假天数，
        TokenUser tu = new TokenUser();
        tu.setId(BusConst.API_IMPORT_USER_ID);//系统管理员
        for (GuideCollar gc : guideCollars) {
            float ml = gc.getMonthlyLeave() == null ? 0 : gc.getMonthlyLeave();//记录当前用户的月假天数
            gc.setMonthlyLeave(ml);//沒有月假為0
            GuideCollarSchedulingAddReq gfs = new GuideCollarSchedulingAddReq();
            gfs.setGuideCollarId(gc.getId());
            gfs.setGuideCollarName(gc.getCnSurname() + gc.getCnName());
            gfs.setArrangementType(GuideCollarSchedulingType.BLANK_DATE.getCode());
            gfs.setWorkingHours(GuideCollarSchedulingWorkHours.ALL_DAY_LONG.getCode());
            gfs.setWorkTypeId(GuideCollarSchedulingServiceImpl.WORKID4);
            gfs.setWorkTypeName(GuideCollarSchedulingServiceImpl.WORKID4_NAME);
            gfs.setRemark("周末自动安排");
            for (LocalDate week : weekDay) {
                gfs.setSchedulingDateBegin(week);
                gfs.setSchedulingDateEnd(week);
                Result add = guideCollarSchedulingService.add(gfs, tu, true);
                if (add.getCode() != 0) {
                    //排班失败说明有任务，就加一天月假
                    gc.setMonthlyLeave(gc.getMonthlyLeave() == null ? 1 : gc.getMonthlyLeave() + 1);
                }
            }
            //月假不相等说明有安排失败的就需要更新数据库
            if (ml != gc.getMonthlyLeave()) {
                newGuideCollars.add(gc);//记录下来批量修改
            }
        }
        return newGuideCollars;
    }

    @Override
    public Result examineTransferAgency() {
        //这里只判断两种类型   如果他是导游就是导游证  如果是林队就是林队证，其它杂七杂八的证件不管
        List<GuideCollarCertificates> gccs = guideCollarCertificatesMapper.selectList(Wrappers.lambdaQuery());
        List<Long> userMessage1 = new ArrayList<>();//证件马上要失效的导领IDS
        List<Long> userMessage2 = new ArrayList<>();//证件马上要失效的导游IDS
        List<Long> updateStatus1 = new ArrayList<>();//证件已经失效的导领IDS
        List<Long> updateStatus2 = new ArrayList<>();//证件已经失效的导游IDS
        gccs.stream().forEach(e -> {
            if (GroupCollarCertificatesType.DYZ.getCode().equals(e.getCertificatesTypeId()) || GroupCollarCertificatesType.LDZ.getCode().equals(e.getCertificatesTypeId())) {
                LocalDate effectiveTime = e.getEffectiveTime();//证件失效时间
                ////当前时间向后推30天     马上要失效了
                if (LocalDate.now().plusDays(30).isEqual(effectiveTime)) {
                    if (GroupCollarCertificatesType.DYZ.getCode().equals(e.getCertificatesTypeId())) {
                        userMessage2.add(e.getGuideCollarId());//导游
                    } else {
                        userMessage1.add(e.getGuideCollarId());//导领
                    }
                }
                //实际失效时间是失效时间的次日凌晨1点（也就是说10号失效的证件在11号凌晨1点修改状态）
                if (LocalDate.now().isEqual(effectiveTime.plusDays(1))) {
                    if (GroupCollarCertificatesType.DYZ.getCode().equals(e.getCertificatesTypeId())) {
                        updateStatus2.add(e.getGuideCollarId());//导游
                    } else {
                        updateStatus1.add(e.getGuideCollarId());//导领
                    }
                }
            }
        });
        Set<Long> longs1 = sysPermissionService.queryPermissionUserIdByMenuId(LDXXGL);//有领队信息菜单的用户
        Set<Long> longs2 = sysPermissionService.queryPermissionUserIdByMenuId(DYXXGL);//有导游信息菜单的用户
        longs1.add(BusConst.API_IMPORT_USER_ID);//超级管理员
        longs2.add(BusConst.API_IMPORT_USER_ID);//超级管理员
        //发送消息 和邮件 并且修改领队状态
        if (userMessage1 != null && userMessage1.size() > 0) {
            updateStatus(userMessage1, GuideCollarTypeTwo.GUIDE.getCode(),
                    GroupCollarCertificatesStatus.CERTIFICATE_STATUS_2.getCode());//领队
            List<GuideCollar> gc = getGc(userMessage1, GuideCollarTypeTwo.GUIDE.getCode());
            sendMessage(gc, longs1, "领队证件即将失效", MessageDataType.DATA_TYPE_9.getCode());//发送通知
        }
        //发送消息 和邮件 并且修改导游状态
        if (userMessage2 != null && userMessage2.size() > 0) {
            updateStatus(userMessage2, GuideCollarTypeTwo.TOUR_GUIDE.getCode(),
                    GroupCollarCertificatesStatus.CERTIFICATE_STATUS_2.getCode());//导游
            List<GuideCollar> gc = getGc(userMessage2, GuideCollarTypeTwo.TOUR_GUIDE.getCode());
            sendMessage(gc, longs1, "导游证件即将失效", MessageDataType.DATA_TYPE_9.getCode());//发送通知
        }
        //发送消息 和邮件 修改领队状态
        if (updateStatus1 != null && updateStatus1.size() > 0) {
            updateStatus(userMessage1, GuideCollarTypeTwo.GUIDE.getCode(),
                    GroupCollarCertificatesStatus.CERTIFICATE_STATUS_3.getCode());//领队
            List<GuideCollar> gc = getGc(updateStatus1, GuideCollarTypeTwo.GUIDE.getCode());
            sendMessage(gc, longs2, "领队证件失效", MessageDataType.DATA_TYPE_10.getCode());//发送通知
        }
        //发送消息 和邮件 修改导游状态
        if (updateStatus2 != null && updateStatus2.size() > 0) {
            updateStatus(userMessage2, GuideCollarTypeTwo.TOUR_GUIDE.getCode(),
                    GroupCollarCertificatesStatus.CERTIFICATE_STATUS_3.getCode());//导游
            List<GuideCollar> gc = getGc(updateStatus2, GuideCollarTypeTwo.TOUR_GUIDE.getCode());
            sendMessage(gc, longs2, "导游证件失效", MessageDataType.DATA_TYPE_10.getCode());//发送通知
        }
        return Result.success();
    }

    /**
     * 发送通知
     *
     * @param gc
     * @param longs1
     */
    private void sendMessage(List<GuideCollar> gc, Set<Long> longs1, String str, Integer dataType) {
        if (gc != null && gc.size() > 0 && longs1 != null && longs1.size() > 0) {
            SysMessageReq smr = new SysMessageReq();
            smr.setSource(OperationLogModel.GUIDE.getModel());
            smr.setType(MessageType.INFORM.getCode());
            smr.setBusinessType(dataType);
            smr.setSendingTime(LocalDateTime.now());
            List<SysMessageReq> list = new ArrayList<>();
            gc.forEach(e -> {
                // 校驗郵箱 不为空且格式正确就发送
                if (StringUtils.isNotEmpty(e.getEmail()) && e.getEmail().matches(emailReg)) {
                    //发送邮件
                    StringBuffer sb = new StringBuffer();
                    sb.append(OperationLogModel.GUIDE.getModel());
                    sb.append("提醒您：");
                    sb.append(e.getCnSurname());
                    sb.append(e.getCnName());
                    sb.append("的");
                    sb.append(str);
                    sb.append(",请及时处理!");
                    mailTemplate.sendSimpleMail(e.getEmail(), OperationLogModel.GUIDE.getModel(), sb.toString());
                }
                smr.setTitle(str);
                smr.setBusinessOrderNo(e.getCnSurname() + e.getCnName());
                smr.setBusinessId(e.getId());
                //循环向有领队信息菜单的用户发送消息
                longs1.forEach(c -> {
                    SysMessageReq copy = EntityUtil.copy(smr, SysMessageReq.class);
                    copy.setReceivingUserId(c);
                    list.add(copy);
                });
            });
            systemMessageService.addAll(list, BusConst.API_IMPORT_USER_ID);
        }
    }

    /**
     * 查询领队或导领
     *
     * @param ids
     * @param type
     * @return
     */
    private List<GuideCollar> getGc(List<Long> ids, Integer type) {
        QueryWrapper<GuideCollar> qwgc = new QueryWrapper<>();
        qwgc.lambda().eq(GuideCollar::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(GuideCollar::getType, type)
                .in(GuideCollar::getId, ids);
        return baseMapper.selectList(qwgc);
    }

    /**
     * 批量修改导领或导游的证件状态
     *
     * @param ids    导领或导游IDS
     * @param type   导领1 导游2
     * @param status 需要修改的证件状态
     * @return
     */
    private int updateStatus(List<Long> ids, Integer type, Integer status) {
        UpdateWrapper<GuideCollar> uwgc = new UpdateWrapper<>();
        uwgc.lambda().eq(GuideCollar::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(GuideCollar::getType, type)
                .in(GuideCollar::getId, ids);
        GuideCollar gc = new GuideCollar();
        gc.setCertificatesStatus(status);
        int update = baseMapper.update(gc, uwgc);
        return update;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result updateInfo(GuideCollarUpdateInfoReq req, TokenUser tokenUser) {
        LocalDateTime now = LocalDateTime.now();
        GuideCollar guideCollar = baseMapper.selectById(req.getId());
        if (guideCollar != null) {
            guideCollar.setModifiedId(tokenUser.getId());
            guideCollar.setGmtModified(now);
            //黑名单和离职是需要改变status状态的
            if (req.getUpdateType() == GuideCollarUpdateType.STATUS_1.getCode()) {
                guideCollar.setTransferAgencyId(req.getTransferAgencyId());
                guideCollar.setTransferAgencyName(req.getTransferAgencyName());
                guideCollar.setTransferAgencyDate(req.getTransferAgencyDate());
                int update = baseMapper.updateById(guideCollar);
                if (update > 0) {
                    //依赖了一个定时任务（每天检索）  如果当天立马生效就直接掉一下任务
                    if (req.getTransferAgencyDate().isEqual(LocalDate.now())) {
                        updateTransferAgency();
                    }
                }
            } else if (req.getUpdateType() == GuideCollarUpdateType.STATUS_2.getCode()) {//黑名单 拉黑时如果有工作安排就拒绝（必须先取消工作安排）
                //检查工作安排
                List<GuideCollarScheduling> userIds = getUserIds(req.getId(), LocalDate.now());
                if (userIds == null || userIds.size() < 1) {//等于空才可以拉黑quitDate
                    guideCollar.setBlacklistReason(req.getBlacklistReason());
                    guideCollar.setStatus(GuideCollarStatus.STATUS_4.getCode());
                } else {
                    return Result.failed(SystemError.GUIDE_41003);
                }
                baseMapper.updateById(guideCollar);
            } else if (req.getUpdateType() == GuideCollarUpdateType.STATUS_3.getCode()) {//升职
                guideCollar.setBePromotedDare(req.getBePromotedDare());
                guideCollar.setBePromotedReason(req.getBePromotedReason());
                guideCollar.setBePromotedLevelId(req.getBePromotedLevelId());
                guideCollar.setBePromotedLevelName(req.getBePromotedLevelName());
                int update = baseMapper.updateById(guideCollar);
                if (update > 0) {
                    //依赖了一个定时任务（每天检索）  如果当天立马生效就直接掉一下任务
                    if (req.getBePromotedDare().isEqual(LocalDate.now())) {
                        topAndBottomTransferAgency();
                    }
                }
            } else if (req.getUpdateType() == GuideCollarUpdateType.STATUS_4.getCode()) {//离职 离职时判断离职时间后不能有工作安排
                //检查最大的工作安排
                List<GuideCollarScheduling> userIds = getUserIds(req.getId(), req.getQuitDate());
                if (userIds == null || userIds.size() < 1) {//离职生效时间之后没有工作安排才能设置离职
                    guideCollar.setQuitReason(req.getQuitReason());
                    guideCollar.setQuitDate(req.getQuitDate());
                } else {
                    return Result.failed(SystemError.GUIDE_41004);
                }
                int update = baseMapper.updateById(guideCollar);
                if (update > 0) {
                    //依赖了一个定时任务（每天检索）  如果当天立马生效就直接掉一下任务
                    if (req.getQuitDate().isEqual(LocalDate.now())) {
                        topAndBottomTransferAgency();
                    }
                }
            }
        }
        return Result.success(req.getId());
    }

    /**
     * 得到当前用户所有的任务（时间大于当前日期并且包含当天）
     *
     * @param id
     * @return
     */
    private List<GuideCollarScheduling> getUserIds(Long id, LocalDate date) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        QueryWrapper<GuideCollarScheduling> gcs = new QueryWrapper<>();
        gcs.lambda().eq(GuideCollarScheduling::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(GuideCollarScheduling::getGuideCollarId, id)
                .ge(GuideCollarScheduling::getSchedulingDate, date);
        List<GuideCollarScheduling> guideCollarSchedulings = guideCollarSchedulingMapper.selectList(gcs);
        return guideCollarSchedulings;
    }


    @Override
    public List<GuideCollarExcelDTO> selectListByIds(GuideCollarQueryExcelReq req) {
        List<GuideCollar> guideCollars = baseMapper.selectBatchIds(req.getIdList());
        List<GuideCollarExcelDTO> guideCollarExcelDTOS = new ArrayList<>();
        for (GuideCollar guideCollar : guideCollars) {
            GuideCollarExcelDTO guideCollarExcelDTO = EntityUtil.copy(guideCollar, GuideCollarExcelDTO.class);
            //拼接区号+手机号
            guideCollarExcelDTO.setMobile(guideCollar.getMainlandMobileAreaCode() + "-" + guideCollar.getMainlandMobile());
            //翻译性别
            guideCollarExcelDTO.setGenderName(convertGenderName(guideCollar.getGender()));
            //翻译状态
            //翻译证件状态
            guideCollarExcelDTOS.add(guideCollarExcelDTO);
        }
        return null;
    }

    private String convertGenderName(Integer gender) {
        if (gender == 1) {
            return "男";
        }
        if (gender == 2) {
            return "女";
        }
        return "";
    }

}
